package com.enki.cigarettes.controller;

import com.enki.cigarettes.controller.vo.request.RechargeRequestVo;
import com.enki.cigarettes.entity.BalanceHistoryT;
import com.enki.cigarettes.entity.RechargeRecordT;
import com.enki.cigarettes.entity.RechargeRuleT;
import com.enki.cigarettes.entity.UserT;
import com.enki.cigarettes.enums.RechargeEnums;
import com.enki.cigarettes.handler.Response;
import com.enki.cigarettes.repository.BalanceHistoryTRepository;
import com.enki.cigarettes.repository.RechargeRecordTRepository;
import com.enki.cigarettes.repository.RechargeRuleTRepository;
import com.enki.cigarettes.repository.UserTRepository;
import com.enki.cigarettes.statics.StaticKeys;
import com.enki.cigarettes.utils.primary.SnowflakeIdUtil;
import com.enki.cigarettes.utils.wechatpay.WXJSAPIPayConfigImpl;
import com.enki.cigarettes.utils.wechatpay.WXParam;
import com.enki.cigarettes.utils.wechatpay.pay.sdk.WXPay;
import com.enki.cigarettes.utils.wechatpay.pay.sdk.WXPayUtil;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.util.*;

/**
 * @author WCS.Wang
 * @version V1.0
 * @Package com.enki.cigarettes.controller
 * @Name e-cigarettes-shop-api-module
 * @Description: TODO 余额逻辑层
 * @date 2019-08-08
 */
@RestController
@RequestMapping("/api/balances")
@Slf4j
public class BalanceController {

    @Autowired
    UserTRepository userTRepository;
    @Autowired
    BalanceHistoryTRepository balanceHistoryTRepository;
    @Autowired
    RechargeRuleTRepository rechargeRuleTRepository;
    @Autowired
    RechargeRecordTRepository rechargeRecordTRepository;

    // H5支付
    private WXJSAPIPayConfigImpl wxjsapiPayConfig;

    public BalanceController() throws Exception {
        wxjsapiPayConfig = WXJSAPIPayConfigImpl.getInstance();
    }

    @ApiOperation(value = "获取余额变动记录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "页码", required = true, dataType = "int"),
            @ApiImplicitParam(name = "size", value = "每页数据", required = true, dataType = "int")
    })
    @GetMapping
    public Object findItemsByPage(@RequestParam(defaultValue = "0") int page,
                                  @RequestParam(defaultValue = "10") int size, HttpSession session) {
        try {
            Object sessionId = session.getAttribute(StaticKeys.USER_ID);
            if (sessionId == null) {
                return Response.unauthorized_401("登录身份失效，请重新登录");
            }
            Sort sort = new Sort(Sort.Direction.DESC, StaticKeys.SORT_CREATE_TIME);
            Pageable pageable = PageRequest.of(page, size, sort);
            Page<BalanceHistoryT> beanPage = balanceHistoryTRepository.findByUserTId(sessionId.toString(), pageable);
            return Response.success(beanPage, StaticKeys.SUCCESS);
        } catch (Exception e) {
            log.error("获取余额记录失败：" + e.getMessage());
            e.printStackTrace();
            return Response.serverError_500("获取余额记录失败");
        }
    }

    @ApiOperation(value = "获取充值信息")
    @GetMapping(value = "/recharge")
    public Object findRechargeData(HttpSession session) {
        try {
            Object sessionId = session.getAttribute(StaticKeys.USER_ID);
            if (sessionId == null) {
                return Response.unauthorized_401("登录身份失效，请重新登录");
            }
            UserT userBean = userTRepository.findOneById(sessionId.toString());
            if (userBean == null) {
                return Response.badRequest_400("登录身份失效，请重新登录");
            }
            Map<String, Object> responseData = new HashMap<>();
            responseData.put("curBalance", userBean.getCurBalance());
            responseData.put("firstRecharge", false);
            // 赠送金额
            responseData.put("giftData", 0);
            List<RechargeRecordT> rechargeRecordList = rechargeRecordTRepository.findByUserTId(sessionId.toString());
            if (rechargeRecordList.size() == 0) {
                RechargeRuleT rechargeRule = rechargeRuleTRepository.findFirstByFirstCharge(true);
                if (rechargeRule != null) {
                    responseData.put("giftData", rechargeRule.getGiftData());
                }
                responseData.put("firstRecharge", true);
            } else {
                RechargeRuleT rechargeRule = rechargeRuleTRepository.findFirstByFirstCharge(false);
                if (rechargeRule != null) {
                    responseData.put("giftData", rechargeRule.getGiftData());
                }
            }
            return Response.success(responseData, StaticKeys.SUCCESS);
        } catch (Exception e) {
            log.error("获取充值信息失败：" + e.getMessage());
            e.printStackTrace();
            return Response.serverError_500("获取充值信息失败");
        }
    }

    @ApiOperation(value = "充值凭证")
    @PostMapping
    public Object recharge(@RequestBody RechargeRequestVo item, HttpSession session) {
        try {
            Object sessionId = session.getAttribute(StaticKeys.USER_ID);
            if (sessionId == null) {
                return Response.unauthorized_401("登录身份失效，请重新登录");
            }
            UserT userBean = userTRepository.findOneById(sessionId.toString());
            if (userBean == null) {
                return Response.badRequest_400("登录身份失效，请重新登录");
            }
            // 赠送百分比
            int giftData = 0;
            // 是否为首充
            boolean firstRecharge = false;
            List<RechargeRecordT> rechargeRecordList = rechargeRecordTRepository.findByUserTId(sessionId.toString());
            if (rechargeRecordList.size() == 0) {
                RechargeRuleT rechargeRule = rechargeRuleTRepository.findFirstByFirstCharge(true);
                if (rechargeRule != null) {
                    giftData = rechargeRule.getGiftData();
                }
                firstRecharge = true;
            } else {
                RechargeRuleT rechargeRule = rechargeRuleTRepository.findFirstByFirstCharge(false);
                if (rechargeRule != null) {
                    giftData = rechargeRule.getGiftData();
                }
            }
            // 编号
            String orderId = SnowflakeIdUtil.getSnowflakeId().nextId() + "";
            int totalAmount = item.getRechargeAmount() * 100;
//            totalAmount = 1;
            String nonce_str = WXPayUtil.generateUUID();
            Map<String, String> orderData = new HashMap<>();
            orderData.put("appid", wxjsapiPayConfig.getAppID());
            orderData.put("mch_id", wxjsapiPayConfig.getMchID());
            orderData.put("nonce_str", nonce_str);
            orderData.put("body", "余额充值，订单号：" + orderId);
            orderData.put("out_trade_no", orderId);
            orderData.put("total_fee", String.valueOf(totalAmount));
            orderData.put("spbill_create_ip", wxjsapiPayConfig.getHostIP());
            orderData.put("notify_url", wxjsapiPayConfig.getNotifyUrl() + "/api/wechat/recharge");
            orderData.put("trade_type", wxjsapiPayConfig.getTradeType());
            orderData.put("sign_type", wxjsapiPayConfig.getSignType());
            orderData.put("openid", userBean.getOpenid());
            String sign = WXPayUtil.generateSignature(orderData, wxjsapiPayConfig.getKey());
            orderData.put("sign", sign);
            Map<String, String> orderResult = new WXPay(wxjsapiPayConfig).unifiedOrder(orderData);
            if (orderResult.get("return_code").equals("SUCCESS") && orderResult.get("return_msg").equals("OK") && orderResult.get("result_code").equals("SUCCESS")) {
                // 预支付交易会话标识
                String prepayId = orderResult.get("prepay_id").toString();
                String timeStamp = Long.toString(System.currentTimeMillis() / 1000);
                Map<String, String> payData = new HashMap<>();
                payData.put("appId", wxjsapiPayConfig.getAppID());
                payData.put("timeStamp", timeStamp);
                payData.put("nonceStr", nonce_str);
                payData.put("package", "prepay_id=" + prepayId);
                payData.put("signType", wxjsapiPayConfig.getSignType());
                String paySign = WXPayUtil.generateSignature(payData, wxjsapiPayConfig.getKey());
                // 封装支付参数
                WXParam wxParam = new WXParam();
                wxParam.setAppid(wxjsapiPayConfig.getAppID());
                wxParam.setTimestamp(timeStamp);
                wxParam.setNonceStr(nonce_str);
                wxParam.setPackages("prepay_id=" + orderResult.get("prepay_id").toString());
                wxParam.setSignType(wxjsapiPayConfig.getSignType());
                wxParam.setSign(paySign);
                // 记录充值
                RechargeRecordT rechargeRecord = new RechargeRecordT();
                rechargeRecord.setId(orderId);
                rechargeRecord.setUserTId(userBean.getId());
                rechargeRecord.setAmount(item.getRechargeAmount() * 100);
                rechargeRecord.setGiftAmount(item.getRechargeAmount() * giftData);
                rechargeRecord.setStatus(RechargeEnums.RechargeStatus.UNPAID.getStatus());
                rechargeRecord.setTransactionId(StaticKeys.NULL);
                rechargeRecord.setPrepayId(prepayId);
                rechargeRecord.setCreateTime(new Date());
                rechargeRecord.setUpdateTime(new Date());
                rechargeRecord.setPayTime(new Date());
                rechargeRecordTRepository.save(rechargeRecord);
                return Response.success(wxParam, StaticKeys.SUCCESS);
            } else {
                return Response.serverError_500("服务器错误，获取支付信息失败");
            }
        } catch (Exception e) {
            log.error("获取充值凭证失败：" + e.getMessage());
            e.printStackTrace();
            return Response.serverError_500("获取充值凭证失败");
        }
    }


}
